home *** CD-ROM | disk | FTP | other *** search
/ Info-Mac 3 / Info_Mac_1994-01.iso / Development / Source / Macintosh Tracker 1.1 Source / Tracker Server Folder / main.c < prev    next >
C/C++ Source or Header  |  1993-05-18  |  12KB  |  411 lines

  1. /* main.c */
  2.  
  3. /* plays sound/noisetracker files on Sparc, silicon graphics.
  4.  * Authors  : Liam Corner - zenith@dcs.warwick.ac.uk
  5.  *            Marc Espie - espie@dmi.ens.fr
  6.  *            Steve Haehnichen - shaehnic@ucsd.edu
  7.  *
  8.  * Usage    : tracker <filename> 
  9.  *  this version plays compressed files as well.
  10.  */
  11.  
  12. /* $Id: main.c,v 3.10 1993/04/25 15:13:36 espie Exp espie $
  13.  * $Log: main.c,v $
  14.  * Revision 3.10  1993/04/25  15:13:36  espie
  15.  * Force new version.
  16.  *
  17.  * Revision 3.9  1993/01/15  14:00:28  espie
  18.  * Added bg/fg test.
  19.  *
  20.  * Revision 3.8  1993/01/06  17:58:39  espie
  21.  * *** empty log message ***
  22.  *
  23.  * Revision 3.7  1992/12/03  15:00:50  espie
  24.  * restore stty.
  25.  *
  26.  * Revision 3.6  1992/11/27  10:29:00  espie
  27.  * General cleanup
  28.  *
  29.  * Revision 3.5  1992/11/24  10:51:19  espie
  30.  * Added loads of new options.
  31.  *
  32.  * Revision 3.4  1992/11/23  17:18:59  espie
  33.  * *** empty log message ***
  34.  *
  35.  * Revision 3.3  1992/11/22  17:20:01  espie
  36.  * Augmented usage.
  37.  *
  38.  * Revision 3.2  1992/11/20  14:53:32  espie
  39.  * Added finetune.
  40.  *
  41.  * Revision 3.1  1992/11/19  20:44:47  espie
  42.  * Protracker commands.
  43.  *
  44.  * Revision 3.0  1992/11/18  16:08:05  espie
  45.  * New release.
  46.  *
  47.  * Revision 2.20  1992/11/17  17:06:25  espie
  48.  * Added PREVIOUS_SONG handling ???
  49.  * Use streamio for new interface (obsolescent signal handlers), and
  50.  * related changes.
  51.  * Cleaned up path reader, and better signal handling.
  52.  * Support for open_file.
  53.  * Added imask.
  54.  * Use transparent decompression/path lookup through open_file/close_file.
  55.  * Added setup_audio().
  56.  * Added some frequency/oversample/stereo change on the fly.
  57.  * Necessitates rightful closing/reopening of audio.
  58.  * Added compression methods. Changed getopt.
  59.  * Separated mix/stereo stuff.
  60.  * Added transpose feature.
  61.  * Added possibility to get back to MONO for the sgi.
  62.  * Added stereo capabilities to the indigo version.
  63.  * Added recovery and reread for automatic recognition
  64.  * of old/new tracker files.
  65.  * Added two level of fault tolerancy.
  66.  * Added more rational options.
  67.  * Moved almost everything to audio and automaton.
  68.  * Structured part of the code, especially replay ``automaton''
  69.  * and setting up of effects.
  70.  *
  71.  * Revision 1.26  1991/11/17  17:09:53  espie
  72.  * Added missing prototypes.
  73.  * Some more info while loading files.
  74.  * Added FAULT env variable, FAULT resistant playing,
  75.  * for playing modules which are not quite correct.
  76.  * Serious bug: dochangespeed was not reset all the time.
  77.  * Check all these parameters, they MUST be reset for
  78.  * each new song.
  79.  * Fixed a stupid bug: when env variable LOOPING was
  80.  * undefined, we got a segv on strcmp.
  81.  * Now we just test for its existence, since this is
  82.  * about all we want...
  83.  * Bug correction: when doing arpeggio, there might not
  84.  * be a new note, so we have to save the old note value
  85.  * and do the arppeggio on that note.
  86.  * Completely added control with OVERSAMPLE and FREQUENCY.
  87.  * Added control flow.
  88.  * Added pipe decompression, so that now you can do
  89.  * str32 file.Z directly.
  90.  * stdin may go away.
  91.  * Added arpeggio.
  92.  * Added vibslide and portaslide.
  93.  * Added speed command.
  94.  * Added signal control.
  95.  * Error checking: there shouldn't be that many
  96.  * segv signals any more.
  97.  * Moved every command to commands.c.
  98.  * Added some debug code for showing the full
  99.  * sequence for a file.
  100.  * Corrected the bug in volume slide: there is
  101.  * no default value, i.e., if it is 0, it is 0,
  102.  * as stupid as it may seem.
  103.  * Added vibrato.
  104.  * Added fastskip/corrected skip.
  105.  * Modified control flow of the player till
  106.  * it looks like something reasonable (i.e.,
  107.  * the structure is more natural and reflects
  108.  * the way stuff is played actually...)
  109.  * Do not restart the sound when we change instruments
  110.  * on the fly. A bit strange, but it works that way.
  111.  * Modified main to use new data structures.
  112.  * The sound player is MUCH cleaner, it uses now
  113.  * a 3-state automaton for each voice.
  114.  * Corrected ruckus with data type of sample.
  115.  */
  116.      
  117.  
  118. #include <stdio.h>
  119. #include <signal.h>
  120. #include <stdlib.h>
  121. #include <string.h>
  122. #include <malloc.h>
  123.      
  124. #include "defs.h"
  125. #include "extern.h"
  126. #include "song.h"
  127. #include "pref.h"
  128.      
  129. #include "getopt.h"
  130.      
  131. LOCAL char *id = "$Id: main.c,v 3.10 1993/04/25 15:13:36 espie Exp espie $";
  132.  
  133. #define USAGE \
  134. "[options] filename [...]\n\
  135. -help               Display usage information\n\
  136. -quiet              Print no output other than errors\n\
  137. -picky              Do not tolerate any faults (default is to ignore all)\n\
  138. -tolerant           Ignore all faults\n\
  139. -mono               Select single audio channel output\n\
  140. -stereo             Select dual audio channel output\n\
  141. -verbose            Show text representation of song\n\
  142. -repeats <count>    Number of repeats (0 is forever) (default 1)\n\
  143. -speed <speed>      Song speed.  Some songs want 60 (default 50)\n\
  144. -mix <percent>      Percent of channel mixing. (0 = spatial, 100 = mono)\n\
  145. -new -old -both     Select default reading type (default is -both)\n\
  146. -frequency <freq>   Set playback frequency in Hz\n\
  147. -oversample <times> Set oversampling factor\n\
  148. -transpose <n>      Transpose all notes up\n\
  149. -show               Show what's going on\n\
  150. -sync               Try to synch audio output with display\n\
  151. \n\
  152. RunTime:\n\
  153. r       restart current song\n\
  154. e,x     exit program\n\
  155. n       next song\n\
  156. p       previous song (experimental)\n\
  157. >       fast forward\n\
  158. <       rewind\n\
  159. S       NTSC tempo\t s\tPAL tempo\n"
  160.  
  161. /* Command-line options. */
  162. LOCAL struct long_option long_options[] =
  163. {
  164.   {"help",              0, 'H'},
  165.   {"quiet",             0, 'Q'}, 
  166.   {"picky",             0, 'P'},
  167.   {"tolerant",          0, 'L'},
  168.   {"new",               0, 'N'},
  169.   {"old",               0, 'O'},
  170.   {"both",              0, 'B'},
  171.   {"mono",              0, 'M'},
  172.   {"stereo",            0, 'S'},
  173.   {"verbose",           0, 'V'},
  174.   {"frequency",         1, 'f'},
  175.   {"oversample",        1, 'o'},
  176.   {"transpose",         1, 't'},
  177.   {"repeats",           1, 'r'},
  178.   {"speed",             1, 's'},
  179.   {"mix",               1, 'm'},
  180.   {"start",             1, 'X'},
  181.   {"cut",               1, '-'},
  182.   {"add",               1, '+'},
  183.   {"show",              0, 'v'},
  184.   {"sync",              0, '='},
  185.   {0,                   0,  0 }
  186. };
  187.  
  188.  
  189. /* global variable to catch various types of errors
  190.  * and achieve the desired flow of control
  191.  */
  192. int error;
  193.  
  194. LOCAL int optvalue(def)
  195. int def;
  196.     {
  197.     int d;
  198.         if (sscanf(optarg, "%d", &d) == 1)
  199.             return d;
  200.         else
  201.             {
  202.             optind--;
  203.             return def;
  204.             }
  205.     }
  206.  
  207. void end_all()
  208.     {
  209.     if (run_in_fg())
  210.         printf("\n");
  211.     do_close_audio();
  212.     sane_tty();
  213.     exit(0);
  214.     }
  215.  
  216. LOCAL struct song *do_read_song(name, type)
  217. char *name;
  218. int type;
  219.     {
  220.     struct song *song;
  221.     FILE *file;
  222.  
  223.     if (run_in_fg())
  224.         fflush(stdout); 
  225.  
  226.     file = open_file(name, "r", getenv("MODPATH"));
  227.     if (!file)
  228.         return NULL;
  229.     song = read_song(file, type); 
  230.     close_file(file);
  231.     return song;
  232.     }
  233.  
  234. int main(argc, argv)
  235. int argc;
  236. char **argv;
  237.     {
  238.     int ask_freq;
  239.     int oversample;
  240.     int stereo;
  241.     int start;
  242.     int transpose;
  243.  
  244.  
  245.     struct pref pref;
  246.     struct song *song;
  247.     BOOL *is_song;
  248.     int c;
  249.     int i;
  250.     int default_type;
  251.  
  252.  
  253.     is_song = (BOOL *)malloc(sizeof(BOOL) * argc);
  254.     if (!is_song)
  255.         end_all();
  256.     for (i = 0; i < argc; i++)
  257.         is_song[i] = FALSE;
  258.  
  259.     start = 0;
  260.     pref.imask = 0;
  261.     pref.bcdvol = 0;
  262.     pref.dump_song = FALSE;
  263.     pref.show = FALSE;
  264.     pref.sync = FALSE;
  265.  
  266.     nonblocking_io();
  267.  
  268.     if (argc == 1)
  269.         {
  270.         fprintf(stderr, "Usage: %s %s", argv[0], USAGE);
  271.         end_all();
  272.         }
  273.  
  274.     ask_freq = read_env("FREQUENCY", 0);
  275.     oversample = read_env("OVERSAMPLE", 1);
  276.     transpose = read_env("TRANSPOSE", 0);
  277.     stereo = !getenv("MONO");
  278.  
  279.     create_notes_table();
  280.  
  281.         /* check the command name for default reading type */
  282.  
  283.     default_type = BOTH;
  284.  
  285.     pref.type = default_type;
  286.     pref.repeats = 1;
  287.     pref.speed = 50;
  288.     pref.tolerate = 1;
  289.  
  290.     for (optind = 1; optind < argc; optind++)
  291.         {
  292.         while ((c = getopt(argc, argv, long_options))
  293.                 != EOF)
  294.             switch(c)
  295.                 {
  296.             case '-':
  297.                 if (strcmp(optarg, "all") == 0)
  298.                     pref.imask = ~0;
  299.                 else
  300.                     pref.imask |= 1L << optvalue(0);
  301.                 break;
  302.             case '+':
  303.                 if (strcmp(optarg, "all") == 0)
  304.                     pref.imask = 0;
  305.                 else
  306.                     pref.imask &= ~ (1L << optvalue(0));
  307.                 break;
  308.             case 'O':   /* old tracker type */
  309.                 pref.type = OLD;
  310.                 break;
  311.             case 'N':   /* new tracker type */
  312.                 pref.type = NEW;
  313.                 break;
  314.             case 'v':
  315.                 pref.show = TRUE;
  316.                 break;
  317.             case '=':
  318.                 pref.sync = TRUE;
  319.                 break;
  320.             case 'B':   /* both tracker types */
  321.                 pref.type = BOTH;
  322.                 break;
  323.             case 'r':   /* number of repeats */
  324.                 pref.repeats = optvalue(0);
  325.                 break;
  326.             case 's':   /* speed */
  327.                 pref.speed = optvalue(50);
  328.                 break;
  329.             case 'M':   /* MONO */
  330.                 stereo = 0;
  331.                 break;
  332.             case 'S':   /* STEREO */
  333.                 stereo = 1;
  334.                 break;
  335.             case 'o':   /* oversample */
  336.                 oversample = optvalue(1);
  337.                 break;
  338.             case 'f':   /* frequency */
  339.                 ask_freq = optvalue(0);
  340.                 break;
  341.             case 't':   /* transpose */
  342.                 transpose = optvalue(0);
  343.                 break;
  344.             case 'P':
  345.                 pref.tolerate = 0;
  346.                 break;
  347.             case 'L':
  348.                 pref.tolerate = 2;
  349.                 break;
  350.             case 'm':   /* % of channel mix. 
  351.                          * 0->full stereo, 100->mono */
  352.                 set_mix(optvalue(30));
  353.                 break;
  354.             case 'X':
  355.                 start = optvalue(0);
  356.                 break;
  357.             case 'H':   /* template */
  358.                 fprintf(stderr, "Usage: %s %s", argv[0], USAGE);
  359.                 end_all();
  360.             case 'V':
  361.                 pref.dump_song = TRUE;
  362.                 }
  363.         if (error == PREVIOUS_SONG)
  364.             for (optind -= 2; optind > 1 && !is_song[optind]; optind--)
  365.                 ;
  366.         if (optind < argc)
  367.             {
  368.             if (run_in_fg())
  369.                 printf("%s:", argv[optind]);
  370.             switch(pref.type)
  371.                 {
  372.             case BOTH:
  373.                 song = do_read_song(argv[optind], NEW);
  374.                 if (!song && error != NEXT_SONG)
  375.                     song = do_read_song(argv[optind], OLD);
  376.                 break;
  377.             case OLD:
  378.                 song = do_read_song(argv[optind], pref.type);
  379.                 break;
  380.                 /* this is explicitly flagged as a new module,
  381.                  * so we don't need to look for a signature.
  382.                  */
  383.             case NEW:
  384.                 song = do_read_song(argv[optind], NEW_NO_CHECK);
  385.                 break;
  386.                 }
  387.             if (song)
  388.                 is_song[optind] = TRUE;
  389.             else
  390.                 {
  391.                 puts("not a song");
  392.                 continue;
  393.                 }
  394.  
  395.             if (pref.dump_song)
  396.                 dump_song(song); 
  397.             transpose_song(song, transpose);
  398.             setup_audio(ask_freq, stereo, oversample, pref.sync);
  399.             play_song(song, &pref, start);
  400.             release_song(song);
  401.             if (run_in_fg())
  402.                 printf("\n");
  403.             }
  404.         }
  405.  
  406.     end_all();
  407.     /* NOT REACHED */
  408.     }
  409.  
  410.  
  411.